package com.hiultra.archive.device.shelve;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.log.StaticLog;
import org.java_websocket.enums.ReadyState;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.HashMap;
import java.util.SortedMap;
import java.util.TreeMap;

@Component("shelvesManager")
public class ShelvesManager implements SocketMessageListener, ApplicationEventPublisherAware {
    private static final Log log = LogFactory.get();

    private ApplicationEventPublisher publisher;

    //private static final String ADB_PATH ="D:\\soft\\adb-fastboot";
    private static final String ADB_PATH = "D:\\scrcpy-win64-v2.7";
    private static final String SOCKET_PATH = "ws://127.0.0.1:12581";
    private static final int WAIT_TIME = 2000;
    private HashMap<String, ShelveListener> shelveListenerHashMap = new HashMap<>();
    private HashMap<String, ShelveInfo> shelveInfoHashMap = new HashMap<>();

    ShelvesSocketClient shelvesSocketClient;

    /**
     * 执行adb命令 连接socket
     *
     * @return
     */
    private boolean setADBAndInit() {
        System.out.println("密集架开始连接：");
        String[] cmd = {"cmd.exe", "/C", "adb", "devices"};
        String output = executeCmd(cmd);
        // 有android设备连接
        if (output.endsWith("device") && (shelvesSocketClient == null)) {
            // 设置ip
            String[] root = {"cmd.exe", "/C", "adb", "root"};
            executeCmd(root);
            waitTime();

//            adb shell ifconfig eth0 192.168.1.100 netmask 255.255.255.0 broadcast 192.168.1.1
//            String[] ipConfig = {"cmd.exe", "/C", "adb", "shell", "ifconfig", "eth0", "172.168.100.100", "netmask", "255.255.0.0", "broadcast", "172.168.100.1"};
//            executeCmd(ipConfig);
//            waitTime();

            String[] forwardCmd = {"cmd.exe", "/C", "adb", "forward", "tcp:12581", "tcp:10086"};
            executeCmd(forwardCmd);
            waitTime();

            String[] reverseCmd = {"cmd.exe", "/C", "adb", "reverse", "tcp:9100", "tcp:9100"};
            executeCmd(reverseCmd);
            waitTime();
            System.out.println("密集架：设置ip");

            String[] stopActivityCmd = {"cmd.exe", "/C", "adb", "shell", "am", "force-stop", "com.hiultra.converter"};
            executeCmd(stopActivityCmd);
            waitTime();

            String[] startActivityCmd = {"cmd.exe", "/C", "adb", "shell", "am", "start", "com.hiultra.converter/.SocketActivity"};
            executeCmd(startActivityCmd);
            waitTime();
            waitTime();
            waitTime();
            System.out.println("密集架：开始成功");
//            String[] stopServiceCmd = {"adb","shell","am","broadcast","-a","NotifyServiceStop","-n","com.hiultra.converter/com.hiultra.converter.ServiceBroadcastReceiver"};
//            executeCmd(stopServiceCmd);
//            waitTime();
//
//            String[] startServiceCmd = {"adb","shell","am","broadcast","-a","NotifyServiceStart","-n","com.hiultra.converter/com.hiultra.converter.ServiceBroadcastReceiver"};
//            executeCmd(startServiceCmd);
//            waitTime();

            initSocketClient();
        } else if(shelvesSocketClient != null){
            String[] stopActivityCmd = {"cmd.exe", "/C", "adb", "shell", "am", "force-stop", "com.hiultra.converter"};
            executeCmd(stopActivityCmd);
            waitTime();

            String[] startActivityCmd = {"cmd.exe", "/C", "adb", "shell", "am", "start", "com.hiultra.converter/.SocketActivity"};
            executeCmd(startActivityCmd);
            waitTime();
            waitTime();

            if (shelvesSocketClient.getReadyState() != ReadyState.OPEN) {
                if (shelvesSocketClient.getReadyState() == ReadyState.NOT_YET_CONNECTED) {
                    if (shelvesSocketClient.isClosed()) {
                        shelvesSocketClient.reconnect();
                    } else {
                        shelvesSocketClient.connect();
                    }
                } else if (shelvesSocketClient.getReadyState() == ReadyState.CLOSED) {
                    shelvesSocketClient.reconnect();
                }
            }
        }else {
            log.error("密集架 Android 设备未连接");
        }
        return true;
    }

    private static void waitTime(int time) {
        try {
            Thread.sleep(WAIT_TIME);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private static void waitTime() {
        waitTime(WAIT_TIME);
    }

    public static void main(String[] args) throws IOException {
        String[] cmd = {"cmd.exe", "/C", "adb.exe", "devices"};
        String output = executeCmd(cmd);
        // 有android设备连接
        if (output.endsWith("device")) {
            String[] root = {"cmd.exe", "/C", "adb", "root"};
            output = executeCmd(root);
            System.out.println(output);
            waitTime();

//            adb shell ifconfig eth0 192.168.1.100 netmask 255.255.255.0 broadcast 192.168.1.1
            String[] ipConfig = {"cmd.exe", "/C", "adb", "shell", "ifconfig", "eth0", "172.168.100.100", "netmask", "255.255.0.0", "broadcast", "172.168.100.1"};
            output = executeCmd(ipConfig);
            System.out.println(output);
            waitTime();

            String[] forwardCmd = {"cmd.exe", "/C", "adb", "forward", "tcp:12581", "tcp:10086"};
            output = executeCmd(forwardCmd);
            System.out.println(output);
            waitTime();

            String[] reverseCmd = {"cmd.exe", "/C", "adb", "reverse", "tcp:9100", "tcp:9100"};
            output = executeCmd(reverseCmd);
            System.out.println(output);
            waitTime();

            String[] stopActivityCmd = {"cmd.exe", "/C", "adb", "shell", "am", "force-stop", "com.hiultra.converter"};
            output = executeCmd(stopActivityCmd);
            System.out.println(output);
            waitTime();

            String[] startActivityCmd = {"cmd.exe", "/C", "adb", "shell", "am", "start", "com.hiultra.converter/.SocketActivity"};
            output = executeCmd(startActivityCmd);
            System.out.println(output);
            waitTime();
//            initSocketClient();
            System.in.read();
        } else {
            log.error("密集架 Android 设备未连接");
        }
    }

    /**
     * 连接android板 socket
     */
    public void initSocketClient() {
        try {
            shelvesSocketClient = new ShelvesSocketClient(new URI(SOCKET_PATH));
            shelvesSocketClient.connect();
            shelvesSocketClient.setSocketMessageListener(this);
        } catch (Exception exception) {
            log.error("密集架 Android Socket Client 错误：" + exception.getMessage());
        }
    }

    /**
     * 执行cmd命令
     *
     * @param command
     * @return
     */
    private static String executeCmd(String[] command) {
        StringBuilder output = new StringBuilder();
        if (command != null && command.length > 0) {
            try {
                ProcessBuilder processBuilder = new ProcessBuilder(command);
                processBuilder.directory(new File(ADB_PATH));

                Process process = processBuilder.start();

                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    output.append(line);
                }
                process.waitFor();

                return output.toString();
            } catch (Exception exception) {
                return "";
            }
        }
        return "";
    }


    /**
     * 开架
     *
     * @param ip
     * @param warehouseCode
     * @param areaCode
     * @param area
     * @param columnNo       从0开始
     * @param shelveListener
     */
    public void open(String ip, String warehouseCode, String areaCode, String area,String faceNo,int columnNo, ShelveListener shelveListener) {
        shelveListenerHashMap.put(ip + "_open", shelveListener);
        SortedMap<Object, Object> data = new TreeMap<Object, Object>() {
            private static final long serialVersionUID = 1L;

            {
                put("area", area);
                put("columnNo", columnNo);
                put("faceNo", faceNo);
                put("sectionNo", 0);
                put("layerNo", 0);
                put("boxNo", 0);
                put("name", "");

            }
        };
        SortedMap<Object, Object> request = new TreeMap<Object, Object>() {
            private static final long serialVersionUID = 1L;

            {
                put("areaCode", areaCode);
                put("code", "open");
                put("data", data);
                put("warehouseCode", warehouseCode);
            }
        };
        String message = JSONUtil.toJsonStr(request);
        System.out.println(message);
        SortedMap<Object, Object> ipMessage = new TreeMap<Object, Object>() {
            private static final long serialVersionUID = 1L;

            {
                put("to", ip);
                put("message", message);
            }
        };

        sendMessage(JSONUtil.toJsonStr(ipMessage));
    }

    /**
     * @param area left right
     */
    public void close(String ip, String warehouseCode, String areaCode, String area, ShelveListener shelveListener) {
        shelveListenerHashMap.put(ip + "_close", shelveListener);

        SortedMap<Object, Object> data = new TreeMap<Object, Object>() {
            private static final long serialVersionUID = 1L;

            {
                put("code", "close");
                put("warehouseCode", warehouseCode);
                put("areaCode", areaCode);
                put("area", area);
            }
        };


        String message = JSONUtil.toJsonStr(data);
        SortedMap<Object, Object> ipMessage = new TreeMap<Object, Object>() {
            private static final long serialVersionUID = 1L;

            {
                put("to", ip);
                put("message", message);
            }
        };

        sendMessage(JSONUtil.toJsonStr(ipMessage));
    }

    // 停止
    public void stop(String ip, String warehouseCode, String areaCode, String area, ShelveListener shelveListener) {
        shelveListenerHashMap.put(ip + "_stop", shelveListener);

        SortedMap<Object, Object> data = new TreeMap<Object, Object>() {
            private static final long serialVersionUID = 1L;

            {
                put("code", "stop");
                put("warehouseCode", warehouseCode);
                put("areaCode", areaCode);
                put("area", area);
            }
        };


        String message = JSONUtil.toJsonStr(data);
        SortedMap<Object, Object> ipMessage = new TreeMap<Object, Object>() {
            private static final long serialVersionUID = 1L;

            {
                put("to", ip);
                put("message", message);
            }
        };

        sendMessage(JSONUtil.toJsonStr(ipMessage));
    }

    // 解锁
    public void unlock(String ip, String warehouseCode, String areaCode, String area, ShelveListener shelveListener) {
        shelveListenerHashMap.put(ip + "_unlock", shelveListener);

        SortedMap<Object, Object> data = new TreeMap<Object, Object>() {
            private static final long serialVersionUID = 1L;

            {
                put("code", "unlock");
                put("warehouseCode", warehouseCode);
                put("areaCode", areaCode);
                put("area", area);
            }
        };

        String message = JSONUtil.toJsonStr(data);
        SortedMap<Object, Object> ipMessage = new TreeMap<Object, Object>() {
            private static final long serialVersionUID = 1L;

            {
                put("to", ip);
                put("message", message);
            }
        };

        sendMessage(JSONUtil.toJsonStr(ipMessage));
    }

    public void sendMessage(String message) {
        if (shelvesSocketClient != null && shelvesSocketClient.isOpen()) {
            shelvesSocketClient.send(message);
        }
    }

    /**
     * android socket 信息
     *
     * @param message
     */
    @Override
    public void onMessage(String message) {
        try {
            JSONObject jsonObject = JSONUtil.parseObj(message);
            // 密集架 ip
            String from = jsonObject.getStr("from");
            String msg = jsonObject.getStr("message");
            // 判断是
            JSONObject msgObject = JSONUtil.parseObj(msg);
            if (msgObject.getStr("state") != null) {
                ShelveResponse shelveResponse = JSONUtil.toBean(msg, ShelveResponse.class);
                String key = from + "_" + shelveResponse.getCode();
                if (shelveListenerHashMap.get(key) != null) {
                    shelveListenerHashMap.get(key).onResponse(shelveResponse);
                }
            } else {
                ShelveInfo shelveInfo = JSONUtil.toBean(msg, ShelveInfo.class);
                shelveInfoHashMap.put(from, shelveInfo);

                // 事件
                ShelveInfoEvent shelveInfoEvent = new ShelveInfoEvent(this, from, shelveInfo);
                publisher.publishEvent(shelveInfoEvent);
            }
        } catch (Exception exception) {

        }
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }


    public void execute() {
        if (shelvesSocketClient == null || shelvesSocketClient.isClosed()) {
            setADBAndInit();
        }
    }

}
